#pragma once
#include <memory>
#include <sys/epoll.h>
#include <unordered_map>

#include "epoller.hpp"
#include "socket.hpp"
#include "common.hpp"
#include "connection.hpp"

/*reactor总体框架*/
class reactor{
    const static int revent_nums=64;
private:
    void distribute(int fd,uint32_t event){//分发事件
        if((event&EPOLLERR)||(event&EPOLLHUP)){
            event=EPOLLIN|EPOLLOUT;//将上述的异常处理用IO来解决
        }

        if(event &EPOLLIN){
            if(connections.count(fd)){
                connections[fd]->_recv();
            }
        }

        if(event &EPOLLOUT){
            if(connections.count(fd)){
                modifier(fd,DEL_EVENT,EPOLLOUT);
                connections[fd]->_send();
            }
        }

    }

    void detect(int timeout){//获取事件
        int n=_epoll.wait(revents,revent_nums,timeout);
        if(n>0){
            for(int i=0;i<n;i++){
                int fd=revents[i].data.fd;
                uint32_t event=revents[i].events;
                distribute(fd,event);//分发事件
            }
        }
    }

    bool IsConectionExist(int fd){//判断该链接是否存在
        return connections.count(fd);
    }
public:
    reactor(){}
    void Init(){

    }

    void Loop(){
        _isrunning=true;
        int timeout=-1;
        while(_isrunning){
            detect(timeout);
        }

        _isrunning=false;
    }

    void stop(){
        _isrunning=false;
    }

    int insert(connect_t con){
        int sockfd=con->GetFd();

        if(IsConectionExist(sockfd)){
            LOG(ERROR)<<"sockfd is execist";
            return -1;
        }

        connections[sockfd]=con;
        _epoll.add(*con);
        con->setown(this);
        return sockfd;
    }

    bool modifier(int sockfd,oper op,uint32_t event){
        if(IsConectionExist(sockfd)){
            uint32_t old_event=connections[sockfd]->GetEvent();
            if(op==ADD_EVENT){//添加新事件
                uint32_t new_event=old_event | event;
                connections[sockfd]->setevent(new_event);
                
            }
            else if(op==DEL_EVENT){//删除旧事件
                uint32_t new_event=old_event ^ event;
                connections[sockfd]->setevent(new_event);
            }
            _epoll.modifer(*connections[sockfd]);
            return true;
        }
        LOG(WARRING)<<"connection not find";
        return false;
    }

    bool erase(int sockfd){
        if(IsConectionExist(sockfd)){
            _epoll.del(*connections[sockfd]);
            connections.erase(sockfd);
            return true;
        }
        return false;
    }
    ~reactor(){};
private:
    bool _isrunning=false;
    epoller _epoll;
    struct epoll_event revents[revent_nums];
    std::unordered_map<int,connect_t> connections;//用来记录当前与服务器进行的链接
};